package com.wkbb.sports.config;

import com.github.pagehelper.PageInfo;
import com.wkbb.common.dto.ResultDTO;
import com.wkbb.common.dto.basic.StudentInfoDto;
import com.wkbb.common.handler.JsonUtil;
import com.wkbb.common.utils.MD5Util;
import com.wkbb.sports.dto.*;
import com.wkbb.sports.feign.BasicFeignService;
import com.wkbb.sports.mapper.BasicMapper;
import com.wkbb.sports.mapper.HlifeTrainMapper;
import com.wkbb.sports.mapper.LekangMapper;
import com.wkbb.sports.model.LekangLogon;
import com.wkbb.sports.model.LekangTest;
import com.wkbb.sports.model.StudentArena;
import com.wkbb.sports.service.RuleService;
import com.wkbb.sports.service.StudentArenaService;
import com.wkbb.sports.service.TrainService;
import com.wkbb.sports.utils.DateUtil;
import com.wkbb.sports.utils.SportsUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Transactional
@Component
@Slf4j
@EnableScheduling
public class TimerTask {

    @Autowired
    LekangMapper lekangMapper;
    @Autowired
    HlifeTrainMapper hlifeTrainMapper;
    @Autowired
    BasicFeignService basicFeignService;
    @Autowired
    TrainService trainService;
    @Autowired
    RuleService ruleService;
    @Autowired
    BasicMapper basicMapper;

//    @Autowired
//    private StudentArenaService studentArenaService;
//    @Scheduled(fixedRate = 1000 * 60 * 60)
//    @Transactional(rollbackFor = Exception.class)

    
//    public void resetFillData() throws Exception{
//        log.info("-------------------------resetFillData开始 ： " + DateUtil.getDate() + "-------------------------");
//        PageInfo<StudentArena> pageInfo = studentArenaService.getListByPage(null,1,10000);
//        for (StudentArena studentArena: pageInfo.getList()){
//            studentArenaService.arenaChange(studentArena);
//        }
//        log.info("-------------------------resetFillData结束 ： " + DateUtil.getDate() + "-------------------------");
//    }


    @Scheduled(fixedRate = 1000 * 3 * 60)
    @Transactional(rollbackFor = Exception.class)
    public void LekangTest() throws Exception{
        log.info("-------------------------乐康测试监测 ： " + DateUtil.getDate() + "-------------------------");
        //3分钟没有更新登录的数据视为结束了当次训练。
        List<LekangLogon> lekangLogonList = lekangMapper.findLogonByTimeOut();
        if (!lekangLogonList.isEmpty()){
            for (LekangLogon logon:lekangLogonList){
                List<LekangTest> testList = lekangMapper.findListByClassId(logon.getClassId());
                if (!testList.isEmpty()){

                    Map<Integer,List<LekangTest>> testMap = new HashMap<>();
                    for (LekangTest test:testList){
                        List<LekangTest> tList = testMap.get(test.getTestItemID());
                        if (tList == null){
                            tList = new ArrayList<>();
                            testMap.put(test.getTestItemID(),tList);
                        }
                        tList.add(test);
                    }

                    //获取班级学生列表
//                    ResultDTO<List<StudentInfoDto>> listResultDTO =  basicFeignService.getStudentInfoListByClassId(null,logon.getClassId());
//                    List<StudentInfoDto> stuList = listResultDTO.getData();
                    Map<String, Object> hashMap = new HashMap<>();
                    hashMap.put("classId",logon.getClassId());
                    List<StudentInfoDto> stuList =  basicMapper.getStudentInfoList(hashMap);
                    if (!stuList.isEmpty()){
                        StudentInfoDto stu = stuList.get(0);
                        for(Map.Entry<Integer,List<LekangTest>> entry : testMap.entrySet()){
                            Integer key = entry.getKey();
                            List<LekangTest> value = entry.getValue();

                            TrainDto train = new TrainDto();
                            train.setProjectType((byte) 2);
                            train.setTrainType((byte) 3);
                            Byte projectKind = toProjectKind(key);
                            train.setProjectKind(projectKind);
                            train.setOrgId(stu.getOrgId());
                            train.setGradeId(stu.getGradeId());
                            train.setGradeName(stu.getGradeName());
                            train.setClassId(stu.getClassId());
                            train.setClassName(stu.getClassName());
                            train.setIsManual(true);
                            train.setMarkType((byte) 1);
                            train.setModelType((byte) 1);

                            //获取评分标准
                            double maleMaxCount = 0.0;
                            double maleMinCount = 999999.0;
                            double maleMaxScore = 0.0;
                            double maleMinScore = 999999.0;
                            double femaleMaxCount = 0.0;
                            double femaleMinCount = 999999.0;
                            double femaleMaxScore = 0.0;
                            double femaleMinScore = 999999.0;
                            double maleTotalCount = 0;
                            double maleTotalScore = 0;
                            double femaleTotalCount = 0;
                            double femaleTotalScore = 0;
                            int maleTotal = 0;
                            int femaleTotal = 0;
                            int passingNum = 0;
                            int excellentNum = 0;

                            //获取评分标准
                            ScoreRuleDto scoreRuleDto = ruleService.queryScoreRule(stu.getGradeId(),projectKind);

                            List<TrainStudentDto> students = new ArrayList<>();
                            for (LekangTest item : value){
                                for (int i = 0;i<stuList.size();i++){
                                    StudentInfoDto s = stuList.get(i);
                                    if (s.stuIndex() == item.getStudentId()){
                                        TrainStudentDto studentDto = new TrainStudentDto();
                                        studentDto.setStudentName(s.getName());
                                        studentDto.setStudentId(s.getUserId());
                                        studentDto.setStudentNo(s.getStudentNo());
                                        studentDto.setSex(Objects.requireNonNull(SportsUtils.getSexValue(s.getSex())).byteValue());
                                        studentDto.setAchievement(item.getScore().toString());

                                        calcStuScore(studentDto,scoreRuleDto);
                                        double totalScore = studentDto.getScore() + studentDto.getPlusScore();
                                        if (studentDto.getScoreLevel() != 4) passingNum++;
                                        if (studentDto.getScoreLevel() == 1) excellentNum++;
                                        if (studentDto.getSex() == 2){
                                            femaleTotal ++;
                                            if (item.getScore() > femaleMaxCount) {
                                                femaleMaxCount = item.getScore();
                                                femaleMaxScore = totalScore;
                                            }
                                            if (item.getScore() < femaleMinCount) {
                                                femaleMinCount = item.getScore();
                                                femaleMinScore = totalScore;
                                            }
                                            femaleTotalCount += item.getScore();
                                            femaleTotalScore += totalScore;
                                        }else{
                                            maleTotal ++;
                                            if (item.getScore() > maleMaxCount) {
                                                maleMaxCount = item.getScore();
                                                maleMaxScore = totalScore;
                                            }
                                            if (item.getScore() < maleMinCount) {
                                                maleMinCount = item.getScore();
                                                maleMinScore = totalScore;
                                            }
                                            maleTotalCount += item.getScore();
                                            maleTotalScore += totalScore;
                                        }

                                        students.add(studentDto);
                                        break;
                                    }
                                }
                            }
                            int totalPeople = maleTotal + femaleTotal;
                            if (totalPeople > 0){

                                double classFast = Math.min(maleMinCount, femaleMinCount);
                                double classSlow = Math.max(maleMaxCount, femaleMaxCount);

                                double minScore = Math.min(maleMinScore, femaleMinScore);
                                double maxScore = Math.max(maleMaxScore, femaleMaxScore);

                                double classAvg = maleTotalCount + femaleTotalCount > 0 ? doubleFormat((maleTotalCount + femaleTotalCount) / totalPeople):0;
                                double avgScore = maleTotalScore + femaleTotalScore > 0 ? doubleFormat((maleTotalScore + femaleTotalScore) / totalPeople):0;

                                train.setClassFast(classFast);
                                train.setClassSlow(classSlow);
                                train.setMinScore(minScore);
                                train.setMaxScore(maxScore);
                                train.setClassAvg(classAvg);
                                train.setAvgScore(avgScore);

                                train.setMaleAvgCount(maleTotalCount > 0 ? doubleFormat(maleTotalCount / maleTotal):0);
                                train.setMaleAvgScore(maleTotalScore > 0 ? doubleFormat(maleTotalScore / maleTotal):0);

                                train.setFemaleAvgCount(femaleTotalCount > 0 ? doubleFormat(femaleTotalCount / femaleTotal):0);
                                train.setFemaleAvgScore(femaleTotalScore > 0 ? doubleFormat(femaleTotalScore / femaleTotal):0);

                                if (maleTotal == 0) {
                                    maleMinCount = 0;
                                    maleMinScore = 0;
                                }
                                if (femaleTotal == 0) {
                                    femaleMinCount = 0;
                                    femaleMinScore = 0;
                                }


                                train.setTrainCount(totalPeople);
                                train.setMaleCount(maleTotalCount);
                                train.setFemaleCount(femaleTotalCount);

                                train.setMaleScore(maleTotalScore);
                                train.setFemaleScore(femaleTotalScore);

                                train.setMaleMinCount(maleMinCount);
                                train.setMaleMinScore(maleMinScore);
                                train.setMaleMaxCount(maleMaxCount);
                                train.setMaleMaxScore(maleMaxScore);

                                train.setMaleTotal(maleTotal);
                                train.setFemaleTotal(femaleTotal);

                                train.setFemaleMinCount(femaleMinCount);
                                train.setFemaleMinScore(femaleMinScore);
                                train.setFemaleMaxCount(femaleMaxCount);
                                train.setFemaleMaxScore(femaleMaxScore);

                                train.setPassingRate(passingNum > 0 ? doubleFormat((double)passingNum / totalPeople):0);
                                train.setExcellentRate(excellentNum > 0 ? doubleFormat((double)excellentNum / totalPeople):0);

                                train.setStudents(students);
                                train.setStartTime(logon.getCreateTime());
                                train.setEndTime(logon.getUpdateTime());
                                train.setTeacherId(logon.getTeacherId());
                                train.setCreateBy(logon.getTeacherName());
                                train.setCreateTime(logon.getUpdateTime());
                                String checkCode = MD5Util.getMD5Code(JsonUtil.stringify(train));
                                train.setCheckCode(checkCode);
                                trainService.addTrain(train);
                            }
                        }
                    }
                    LekangTest t1 = testList.get(0);
                    lekangMapper.update(t1);
                }
                logon.setStatus(1);
                lekangMapper.updateLogon(logon);
            }
        }
    }

    private double doubleFormat(Double d){
        return (int)(d * 100) / 100.0;
    }

    private void calcStuScore(TrainStudentDto stu, ScoreRuleDto scoreRuleDto){
        if (scoreRuleDto != null){
            double value = Double.parseDouble(stu.getAchievement());
            if (scoreRuleDto.getPluses() != null){
                List<ScoreRulePlusDto> items = scoreRuleDto.getPluses().stream().filter(it -> it.getSex().equals(stu.getSex())).collect(Collectors.toList());
                for (ScoreRulePlusDto it: items){
                    if (value >= it.getMin() && value < it.getMax()) {
                        stu.setScoreLevel(1);
                        stu.setScore(scoreRuleDto.getScore());
                        stu.setPlusScore(it.getScore());
                        return;
                    }
                }
            }
            if (scoreRuleDto.getItems() != null){
                List<ScoreRuleItemDto> items = scoreRuleDto.getItems().stream().filter(it -> it.getSex().equals(stu.getSex())).collect(Collectors.toList());
                for (ScoreRuleItemDto it: items){
                    if (value >= it.getMin() && value < it.getMax()) {
                        stu.setScoreLevel(it.getScoreLevel());
                        stu.setScore(it.getScore());
                        stu.setPlusScore(0.0);
                        return;
                    }
                }
            }
        }
        if (stu.getScore() == null){
            stu.setScore(0.0);
            stu.setPlusScore(0.0);
            stu.setScoreLevel(4);
        }
    }

    private Byte toProjectKind(Integer itemId){
        switch (itemId){
            case 4://肺活量
                return 8;
            case 6://体前屈
                return 9;
            case 8://仰卧起坐
                return 11;
            case 9://引体向上
                return 12;
            case 29://往返跑
                return 13;
            case 12://实心球
                return 14;
            case 14://握力
                return 15;
            case 18://俯卧撑
                return 16;
            case 23://闭眼单脚站立
                return 17;
            case 26://篮球运球
                return 18;
            case 25://足球运球
                return 19;
            default:
                return itemId.byteValue();
        }
    }
}
